<?php

namespace Lib;

final class Paginator {
    
    protected $_request  = null;
    protected $_name     = null;
    protected $_mapper   = null;
    protected $_callback = null;
    protected $_page     = 1;
    protected $_perPage  = 10;
    protected $_order    = 'id DESC';
    protected $_where    = [];

    public function __construct($name) {
        $request = \Yaf\Dispatcher::getInstance()->getRequest();
        
        $this->_page    = max(1, (int)$request->get('page', 1));
        $this->_perPage = min(30, (int)$request->get('per_page', 10)); 
        $this->_request = $request;
        $this->_name    = $name;
        
        $this->mapper();
    }
    
    /**
     * @return \Mapper\Base\AbstractModel
     */
    public function getMapper() {
        return $this->_mapper;
    }
    
    /**
     * 排序
     * 
     * @param string $order
     * @return \Lib\Paginator
     */
    public function order($order) {
        $this->_order = (string)$order;
        
        return $this;
    }

    /**
     * 条件
     * 
     * @param array $where
     * @return \Lib\Paginator
     */
    public function where($where) {
        $this->_where = $where;
        
        return $this;
    }
    
    /**
     * 页面
     * 
     * @return int
     */
    public function getPage() {
        return $this->_page;
    }
    
    /**
     * 每页个数
     * 
     * @return int
     */
    public function getPerpage() {
        return $this->_perPage;
    }
    
    /**
     * 数据总数
     * 
     * @return int
     */
    public function count() {
        return $this->getMapper()->count($this->_where);
    }
    
    /**
     * 设置回调
     * 
     * @param callable $callback
     * @return \Lib\Paginator
     */
    public function setCallback(callable $callback) {
        $this->_callback = $callback;
        
        return $this;
    }

    /**
     * 数据列表
     * 
     * @return array
     */
    public function lists() {
        $mapper = $this->getMapper();
        $limit  = $this->_perPage;
        $offset = $limit * ($this->_page - 1);
        $lists  = $mapper->fetchAll($this->_where, $this->_order, $limit, $offset);
        
        if(is_callable($this->_callback) && !empty($lists)) {
            $items = $lists;
            $lists = [];
            
            foreach ($items as $index => $item) {
                $lists[$index] = call_user_func_array($this->_callback, [$item]);
            }
        }
        
        return $lists;
    }
    
    /**
     * Model
     * 
     * @return boolean
     * @throws \Exception
     */
    protected function mapper() {
        $mapper = call_user_func([sprintf('\\Mapper\\%sModel', ucfirst($this->_name)), 'getInstance']);
        
        if(!$mapper instanceof \Mapper\Base\AbstractModel) {
            throw new \Exception('invalid name');
        }
     
        $this->_mapper = $mapper;
        
        return true;
    }
}
